// Original from Marching Cubes Example Program 
// by Cory Bloyd (corysama@yahoo.com)
// For a description of the algorithm go to
// http://astronomy.swin.edu.au/pbourke/modelling/polygonise/
#pragma once
#include <zGraphicsConfig.hpp>
#include <Math/Array.hpp>
#include <Math/Vector3.hpp>
#include "../Graphics/AABB.hpp"
#include "../Resource/Mesh/SimpleMesh.hpp"

namespace zzz{
class ZGRAPHICS_CLASS MarchingCubes {
public:
  MarchingCubes();

  void SetSampler(float isoValue, float &sampler(const Vector3f &, const vector<Vector3f> &)=NULL);
  void SetCubeSize(float cubesize);

  void Polygonize(const vector<Vector3f> &points, const AABB<3,float> &aabb, SimpleMesh &mesh);
  void Polygonize(const Array<3,float> &cubevalues, const Vector3f &ori, SimpleMesh &mesh);
  void Polygonize2(const vector<Vector3f> &points, const AABB<3,float> &aabb, SimpleMesh &mesh);
  void Polygonize2(const Array<3,float> &cubevalues, const Vector3f &ori, SimpleMesh &mesh);


private:
  float isoValue_, cubeSize_;
  float (*sampler_)(const Vector3f &, const vector<Vector3f> &);
  float getOffset(float fValue1, float fValue2, float fValueDesired) const;

  void SampleArray(const vector<Vector3f> &points, const AABB<3,float> &aabb, Array<3,float> &cubevalues);
  void MarchTetrahedron(const Vector<4,Vector3f> &pasTetrahedronPosition, const Vector4f &pafTetrahedronValue, SimpleMesh &mesh);

  static int TetrahedronEdgeFlags[16];
  static int TetrahedronTriangles[16][7];
  static int CubeEdgeFlags[256];
  static int TriangleConnectionTable[256][16];
  static const Vector3ui VertexOffset[8];
  static const int EdgeConnection[12][2];
  static const Vector3i EdgeDirection[12];
  static const int TetrahedronEdgeConnection[6][2];
  static const int TetrahedronsInACube[6][4];


};
}